/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-08-18 16:07:09
 * @LastEditTime: 2021-09-06 14:54:56
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */

#include "fgdma.h"
#include "ft_types.h"
// #include "gicv3.h"
#include "interrupt.h"
#include <string.h>
#include "ft_debug.h"
#define GDMA_TEST_DEBUG_TAG "GDMA_TEST"
#define GDMA_TEST_ERROR(format, ...) FT_DEBUG_PRINT_E(GDMA_TEST_DEBUG_TAG, format, ##__VA_ARGS__)
#define GDMA_TEST_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GDMA_TEST_DEBUG_TAG, format, ##__VA_ARGS__)
#define GDMA_TEST_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GDMA_TEST_DEBUG_TAG, format, ##__VA_ARGS__)
#define GDMA_TEST_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GDMA_TEST_DEBUG_TAG, format, ##__VA_ARGS__)

#define BUFFER_BYTESIZE 1024

FGdma gdma0;
FGdmaDataConfig data_config;

volatile u8 src_buffer[BUFFER_BYTESIZE] __attribute__((aligned(256)));
volatile u8 dest_buffer[BUFFER_BYTESIZE] __attribute__((aligned(256)));
volatile u32 dma_trans_done = 0;

#ifdef CONFIG_GDMA_BDL_MODE
#define BUFFER_PER_BYTESIZE 128
struct FGdmaBdlDesc bdl_desc[BUFFER_BYTESIZE / BUFFER_PER_BYTESIZE] __attribute__((aligned(256)));
#endif

static void IrqTestInit(void)
{
    /* interrupt init */

}

static void FGdmaTestHwInit(void)
{
    FGdmaCfgInitialize(&gdma0, FGdmaLookupConfig(FGDMA_INSTANCE0));
}

static void FGdmaIrqCb(u32 status, void *args)
{
    switch (status)
    {
    case FGDMA_IRQ_STATUS_FIFO_EMPTY:
        break;
    case FGDMA_IRQ_STATUS_FIFO_FULL:
        break;
    case FGDMA_IRQ_STATUS_BDL_END:
        GDMA_TEST_DEBUG_I("BDL_END");
        dma_trans_done = 1;
        break;
    case FGDMA_IRQ_STATUS_TRANS_END:
        GDMA_TEST_DEBUG_I("TRANS_END");
        dma_trans_done = 1;
        break;
    case FGDMA_IRQ_STATUS_BUSY:
        break;
    case FGDMA_IRQ_STATUS_OTHER:
        break;
    default:
        break;
    }
}

void FGdmaTest(void)
{
    u32 i;
    IrqTestInit();
    FGdmaTestHwInit();
    FGdmaSetOption(&gdma0, FGDMA_OP_WRITE_QOS_MODE);
    FGdmaSetOption(&gdma0, FGDMA_OP_READ_QOS_MODE);
    FGdmaIrqSetHandler(&gdma0, FGdmaIrqCb, NULL);
    InterruptSetPriority(gdma0.config.irq_num, 0);
    InterruptInstall(gdma0.config.irq_num, FGdmaIrqHandler, &gdma0, "gdma0");
    InterruptUmask(gdma0.config.irq_num);

    for (i = 0; i < BUFFER_BYTESIZE; i++)
    {
        src_buffer[i] = i;
    }

#ifdef CONFIG_GDMA_DIRECT_MODE

    data_config.dma_src_addr_l = ((uintptr)src_buffer & 0xFFFFFFFF);
#ifdef __aarch64__
    data_config.dma_src_addr_h = (((uintptr)src_buffer >> 32) & 0xFFFFFFFF);
#else
    data_config.dma_src_addr_h = 0;
#endif

    data_config.dma_dst_addr_l = ((uintptr)dest_buffer & 0xFFFFFFFF); // For direct
#ifdef __aarch64__
    data_config.dma_dst_addr_h = (((uintptr)dest_buffer >> 32) & 0xFFFFFFFF);
#else
    data_config.dma_dst_addr_h = 0;
#endif
    data_config.data_len = BUFFER_BYTESIZE; // For direct
    data_config.direction = FGDMA_MEM_TO_MEM;
    FGdmaTransfer(&gdma0, FGDMA_CH0_INDEX, &data_config);
#else

    for (i = 0; i < BUFFER_BYTESIZE / BUFFER_PER_BYTESIZE; i++)
    {
        bdl_desc[i].desc_src_addr_l = (((uintptr)&src_buffer[i * BUFFER_PER_BYTESIZE]) & 0xffffffff);
#ifdef __aarch64__
        bdl_desc[i].desc_src_addr_h = (((uintptr)&src_buffer[i * BUFFER_PER_BYTESIZE]) >> 32) & 0xffffffff;
#else
        bdl_desc[i].desc_src_addr_h = 0;
#endif

        bdl_desc[i].desc_dst_addr_l = (((uintptr)&dest_buffer[i * BUFFER_PER_BYTESIZE]) & 0xffffffff);
#ifdef __aarch64__
        bdl_desc[i].desc_dst_addr_h = (((uintptr)&dest_buffer[i * BUFFER_PER_BYTESIZE]) >> 32) & 0xffffffff;
#else
        bdl_desc[i].desc_dst_addr_h = 0;
#endif
        bdl_desc[i].desc_src_tc = 0;
        bdl_desc[i].desc_dst_tc = 0;
        bdl_desc[i].desc_data_len = BUFFER_PER_BYTESIZE;
        bdl_desc[i].desc_rise_irq = BUFFER_PER_BYTESIZE;
    }

    FGdmaBdlTransfer(&gdma0, FGDMA_CH0_INDEX, FGDMA_MEM_TO_MEM, bdl_desc, BUFFER_BYTESIZE / BUFFER_PER_BYTESIZE);
#endif

    while (dma_trans_done == 0)
    {
    }

    GDMA_TEST_DEBUG_I("DMA transfer complete$0 \r\n");

    if (0 == memcmp((u8 *)src_buffer, (u8 *)dest_buffer, BUFFER_BYTESIZE))
    {
        GDMA_TEST_DEBUG_I(" DMA TRANSFER SUCCESSFUL! ");
    }
    else
    {
        GDMA_TEST_DEBUG_E(" DMA TRANSFER FAILED! ");
    }
}